package io.kiki.sba.registry.server.clientInterface.connections;


import io.kiki.sba.registry.api.Server;
import io.kiki.sba.registry.api.exchange.DataExchanger;
import io.kiki.sba.registry.common.model.ClientToClientInterfaceServerNodeId;
import io.kiki.sba.registry.common.model.constants.ValueConstants;
import io.kiki.sba.registry.net.NetUtil;
import io.kiki.sba.registry.remoting.netty.Channel;
import io.kiki.sba.registry.server.clientInterface.bootstrap.Config;
import io.kiki.sba.registry.server.clientInterface.mapper.ConnectionMapper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;
import java.util.stream.Collectors;

public class ConnectionsService {

    @Autowired
    DataExchanger boltDataExchanger;

    @Autowired
    Config config;

    @Autowired
    ConnectionMapper connectionMapper;

    public List<String> getConnections() {
        Server server = boltDataExchanger.getServer(config.getServerPort());
        return server.getChannelList().stream().map(channel -> channel.getRemoteAddress().getAddress().getHostAddress() + ":" + channel.getRemoteAddress().getPort()).collect(Collectors.toList());
    }


    public List<ClientToClientInterfaceServerNodeId> getIpConnects(Set<String> ipSet) {
        return markChannelAndGetIpConnects(ipSet, null, null);
    }


    public List<ClientToClientInterfaceServerNodeId> markChannelAndGetIpConnects(Set<String> ipSet, String key, Object value) {
        Server server = boltDataExchanger.getServer(config.getServerPort());
        if (server == null || CollectionUtils.isEmpty(ipSet)) {
            return Collections.emptyList();
        }
        List<ClientToClientInterfaceServerNodeId> list = new ArrayList<>();
        Collection<io.kiki.sba.registry.api.Channel> channelList = server.getChannelList();
        for (io.kiki.sba.registry.api.Channel channel : channelList) {
            String ip = channel.getRemoteAddress().getAddress().getHostAddress();
            if (ipSet.contains(ip)) {
                if (StringUtils.isNotBlank(key)) {
                    Channel channel1 = (Channel) channel;
                    channel1.setChannelAttribute(key, value);
                }
                list.add(ClientToClientInterfaceServerNodeId.of(channel.getRemoteAddress(), channel.getLocalAddress()));
            }
        }

        return list;
    }

    public List<io.kiki.sba.registry.api.Channel> getAllChannel() {
        Server server = boltDataExchanger.getServer(config.getServerPort());
        if (server == null) {
            return Collections.emptyList();
        }

        return server.getChannelList();
    }


    public List<String> closeIpConnects(List<String> ipList) {
        Server server = boltDataExchanger.getServer(config.getServerPort());
        if (server == null || CollectionUtils.isEmpty(ipList)) {
            return Collections.emptyList();
        }
        List<String> connections = new ArrayList<>();
        Collection<io.kiki.sba.registry.api.Channel> channelList = server.getChannelList();
        Set<String> ipSet = new HashSet<>(ipList);
        for (io.kiki.sba.registry.api.Channel channel : channelList) {
            String key = NetUtil.toAddressString(channel.getRemoteAddress());
            String ip = getIpFromConnectId(key);
            if (ipSet.contains(ip)) {
                server.close(channel);
                connections.add(key + ValueConstants.CONNECT_ID_SPLIT + NetUtil.toAddressString(channel.getLocalAddress()));
            }
        }
        return connections;
    }

    public String getIpFromConnectId(String connectId) {
        if (connectionMapper.contains(connectId)) {
            return connectionMapper.get(connectId);
        } else {
            return connectId.substring(0, connectId.indexOf(':'));
        }
    }
}
